#!/usr/bin/env python
#
# solver.py is part of pyStrips
# Copyright (C) - 2009 - Juan B. Cabral <jbcabral_89@yahoo.com.ar>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


################################################################################
# DOCS
################################################################################

'''Resolves a Strips Structure'''

################################################################################
# IMPORTS
################################################################################

import threading
import random

import common
import structs
import error


################################################################################
# SOLVER
################################################################################

class Solver(threading.Thread):
    def __init__(self, s_group):
        super(Solver, self).__init__()
        self.s_group = s_group
        self.solutions = []
        self._stk_limit = 0
        for op in s_group.operators:
            self._stk_limit += len(op.add_list) - len(op.del_list)
        if self._stk_limit == 0:
            self._stk_limit = 1
        self._stk_limit = abs(self._stk_limit) * 100
        
    def _create_internal_state(self, state):
        stype = common.RW_STATE_INTERNAL
        preds = list(state.preds)
        return structs.State(stype, stype, preds, stype)
    
    def _select_op(self, stk):
        pass
    
    def _solve(self, init_state, goal_state):
        actual_state = self._create_internal_state(init_state)
        solution = structs.Solution(init_state, goal_state)
        stk = structs.Stack(self._stk_limit, goal_state)
        stk.push(goal_state.preds)
        while actual_state != goal_state and stk.in_limit():
            from_stk = stk.pop()
            if isinstance(from_stk, structs.Operator):
                from_stk(actual_state)
            else:
                op = self._select_op(from_stk)
                stk.push(from_stk)
                stk.push(op)
        self.solutions.append(solution)
        
    def run(self):
        for init_state in self.s_group.init_states:
            for goal_state in self.s_group.goal_states:
                self._solve(init_state, goal_state)

################################################################################
# GLOBAL FUNCTIONS
################################################################################

def _still_running(solvers):
    for solver in solvers:
        if solver.is_alive():
            return True
    return False

def solve(s_group, thread_n):
    solvers = []
    for idx in range(thread_n):
        solver = Solver(s_group)
        solver.start()
        solvers.append(solver)
    while _still_running(solvers): pass
    

################################################################################
# MAIN
################################################################################

if __name__ == '__main__':
    print(__doc__)
